<template>
  <div class="card">
    <MyHeader/>
    <div class="body">
      <div class="b_header">
        <div class="task_num">{{ tasks.length }} tasks</div>
        <ul class="b_header_tab">
          <li @click="tabClickHandler(index)" class="tab_item" :class="index === tab.current ? 'active' : ''"
              v-for="(item, index) in tab.tabItem" :key="item.id">{{ item.title }}
          </li>

        </ul>
      </div>
      <div class="input">
        <input @keydown.enter="addHandler" v-model="taskName" type="text"
               placeholder="请输入事件名称,回车添加,双击编辑">
      </div>
      <Empty title="暂无事项" v-if="!tasks.length"/>
      <transition-group :duration="{
                enter: 1000,
                leave: 1000
            }" :enter-active-class="'animate__animated ' + animations?.lists[animations?.current]?.enterClass"
                        :leave-active-class="'animate__animated ' + animations?.lists[animations?.current]?.leaveClass"
                        tag="ul"
                        v-else class="tasks">
        <li class="task" v-for="task in tasks" :key="task.taskID">
          <CheckBox @on-click="checkBoxClickHandler" class="t_checkbox" :task="task"/>
          <div @click.stop="preview(task)" @dblclick.stop="openEdit(task)" v-if="!task.isEdit" :class="task.checked ? 'done' : ''"
               class="name">{{
              task.taskName
            }}
          </div>
          <input @keydown.enter="blurHandler(task)" @blur="blurHandler(task)" v-focus class="name" v-else
                 type="text" v-model="task.taskName"/>
          <div class="del" @click="delHandler(task)">删除</div>

        </li>
      </transition-group>
      <div @click="delByDoneHandler" v-if="tasks.length && tab.current === 0" class="del-by-done">删除已完成</div>
    </div>
  </div>
  <Teleport to="body">
    <transition enter-active-class="animate__animated animate__backInDown"
                leave-active-class="animate__animated animate__backOutDown">
      <TaskPreview :taskData="taskData" @close="previewShow=false" v-if="previewShow"/>
    </transition>
  </Teleport>
</template>
<script setup lang="ts">
import {reactive, ref, watchEffect, onMounted, Directive} from 'vue';
import TaskPreview from './TaskPreview.vue'
import type {Ref} from 'vue';
import {nanoid} from 'nanoid';
import CheckBox from './CheckBox.vue';
import MyHeader from './Header.vue';
import Empty from './Empty.vue';
import {getLocalStorageData, setLocalStorageData} from '../../../utils/local';
import 'animate.css'

type Task = {
  taskID: string,
  taskName: string,
  checked: boolean,
  time: number,
  isEdit: boolean
}
type TabItem = {
  id: string,
  title: string
}
type Tab = {
  current: number,
  tabItem: Array<TabItem>
}
type List = {
  aid: string,
  leaveClass: string,
  enterClass: string,
  name: string,
}
type Animation = {
  current: number,
  lists: Array<List>
}
const taskData: Ref<Task> = ref({
  taskID: '',
  taskName: '',
  checked: false,
  time: 0,
  isEdit: false
})
const previewShow = ref(false)
const tasks = reactive<Array<Task>>([])
const tab = reactive<Tab>({
  current: 0,
  tabItem: [{id: nanoid(), title: '全部'}, {id: nanoid(), title: '进行中'}, {id: nanoid(), title: '已完成'}]
})
const taskName = ref('')
const animations: Ref<Animation> = ref({current: -1, lists: []})
const getAllAnimation = () => {
  const animationsLocal = getLocalStorageData('animations')
  animations.value = animationsLocal
}
/**
 * 获取焦点（自定义指令）
 */
const vFocus: Directive = {
  mounted(el: HTMLInputElement) {
    el.focus()
  }
}
/**
 * 开启编辑
 * @param task 任务数据
 */
const openEdit = (task: Task) => {
  task.isEdit = true
}

/**
 * 预览任务
 * @param task
 */
const preview = (task: Task) => {
  previewShow.value = true
  taskData.value = task
}
/**
 * 失去焦点
 * @param task 任务数据
 */
const blurHandler = (task: Task) => {
  task.isEdit = false
  if (!task.taskName) {
    getTaskData()
    return
  }
  setLocalStorageData('todolist', tasks)
}
/**
 * 删除所有完成的事项
 */
const delByDoneHandler = () => {
  const filter = tasks.filter(x => !x.checked)
  tasks.length = 0
  tasks.push(...filter)
  setLocalStorageData('todolist', tasks)
}
/**
 * 获取事项数据
 * @param current tab索引
 */
const getTaskData = (current: number = 0) => {
  tasks.length = 0
  const todolist = getLocalStorageData('todolist')
  if (todolist?.length) {
    todolist?.sort((a: Task, b: Task) => {
      return b.time - a.time
    })
    switch (current) {
      case 0:
        return tasks.push(...todolist)
      case 1:
        return tasks.push(...todolist.filter((x: Task) => !x.checked))
      case 2:
        return tasks.push(...todolist.filter((x: Task) => x.checked))
      default:
        break;
    }
  }
}


watchEffect(() => {
  const current = tab.current
  getTaskData(current)
})
/**
 * tab栏点击业务逻辑处理
 * @param item tab数据
 * @param index 索引
 */
const tabClickHandler = (index: number): void => {
  if (tab.current === index) return
  tab.current = index
}
/**
 * 复选框点击业务逻辑处理
 * @param task 事件数据
 */
const checkBoxClickHandler = (task: Task) => {
  task.checked = !task.checked
  setLocalStorageData('todolist', tasks)
}
/**
 * 删除事件
 * @param task 事件数据
 */
const delHandler = (task: Task) => {
  const index = tasks.findIndex(x => x.taskID === task.taskID)
  tasks.splice(index, 1)
  setLocalStorageData('todolist', tasks)
}
/**
 * 添加事件业务逻辑处理
 */
const addHandler = () => {
  if (!taskName.value) return
  const obj: Task = {
    taskID: nanoid(),
    taskName: taskName.value,
    time: Date.now(),
    checked: false,
    isEdit: false
  }
  tasks.push(obj)
  taskName.value = ''
  setLocalStorageData('todolist', tasks)
  getTaskData()
}
onMounted(() => {
  getAllAnimation()
})

</script>
<style lang="less" scoped>
/* 1. 声明过渡效果 */
.list-move,
.list-enter-active,
.list-leave-active {
  transition: all 0.5s cubic-bezier(0.55, 0, 0.1, 1);
}

/* 2. 声明进入和离开的状态 */
.list-enter-from,
.list-leave-to {
  opacity: 0;
  transform: scaleY(0.01) translate(2rem, 0);
}

/* 3. 确保离开的项目被移除出了布局流
      以便正确地计算移动时的动画效果。 */
.list-leave-active {
  position: absolute;
}

.card {
  background-color: #fff;
  width: 60%;
  margin: 0 auto;
  margin-top: 1.8rem;
  border-radius: 0.8rem;
  padding: 1rem;
  box-shadow: 0 1.5rem 3rem rgba(0, 0, 0, 0.3);


  .body {
    color: #333;
    font-size: 1.6rem;
    padding: 0 1rem;
    margin-top: 1rem;

    .b_header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      color: #8a9ca5;
      user-select: none;


      .b_header_tab {
        display: flex;
        font-size: 1.2rem;

        .tab_item {
          margin-left: 1rem;
          cursor: pointer;
          padding: 0.6rem;
          border-radius: 4.3rem;
          transition: all .3s ease;

          &:hover {
            box-shadow: inset 0.3rem 0.3rem 0.8rem #c5c5c5,
              inset -0.3rem -0.3rem 0.8rem #fbfbfb;
          }

          &.active {
            box-shadow: inset 0.3rem 0.3rem 0.8rem #c5c5c5,
              inset -0.3rem -0.3rem 0.8rem #fbfbfb;
          }
        }
      }

    }

    .input {
      width: 100%;

      input {
        padding: 0.8rem 0;
        color: #333;
        width: 100%;
        outline: none;
        border: 0;
        font-size: 1rem;
        border-bottom: #ddd solid 2px;
      }
    }

    .tasks::-webkit-scrollbar {
      width: 0 !important
    }

    .del-by-done {
      user-select: none;
      box-sizing: border-box;
      background-color: #F56C6C;
      color: #fff;
      align-self: flex-end;
      font-size: 1rem;
      display: flex;
      align-items: center;
      justify-content: center;
      border-radius: 0.4rem;
      padding: 0.8rem;
      cursor: pointer;
      overflow: hidden;
      transition: all .3s ease-out;

      &:hover {
        background-color: #f56c6cdb;
      }
    }


    .tasks {
      padding: 0 0.5rem;
      padding-top: 0.8rem;
      margin-top: 0.5rem;
      font-size: 1.5rem;
      color: #333;
      height: 60vh;
      overflow-y: auto;


      .task {
        display: flex;
        align-items: center;
        position: relative;
        margin-bottom: 1.5rem;

        input[type='text'] {
          outline: none;
          border: 0;
          font-size: 20px;
          font-weight: bold;
        }


        &:last-child {
          margin-bottom: 0;
        }

        &:hover .del {
          visibility: visible;
        }


        .name {
          flex-grow: 2;
          margin-left: 0.8rem;
          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
          padding-right: 3.5rem;
          cursor: pointer;

          &.done {
            color: #8a9ca5;
          }
        }

        .del {
          user-select: none;
          visibility: hidden;
          box-sizing: border-box;
          position: absolute;
          background-color: #F56C6C;
          color: #fff;
          align-self: flex-end;
          font-size: 1rem;
          display: flex;
          align-items: center;
          justify-content: center;
          border-radius: 0.4rem;
          padding: 0.8rem;
          right: 0;
          top: 50%;
          transform: translateY(-50%);
          cursor: pointer;
          overflow: hidden;
          transition: all .3s ease-out;

          &:hover {
            background-color: #f56c6cdb;
          }
        }
      }
    }

  }
}
</style>